//-----------------------------------------------------------------------
// <copyright file="InstallPatch.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Shaun Wilde (ICS)</author>
// <email>v-swilde</email>
// <date>2006-09-07</date>
// <summary>
//  Install a patch - pass non embedded properties on the command line
// </summary>
//-----------------------------------------------------------------------

namespace Microsoft.Sdc.Tasks.Msi
{
  using System;
  using System.Collections.Generic;
  using System.Text;
  using Microsoft.Build.Framework;
  using Microsoft.Build.Utilities;

  #region Class Comments
  /// <summary>
  /// Installs an MSI Patch. The patch will use properties that are already part of the 
  /// current MSI that it is being patched, other properties can be passed during execution 
  /// via the command line. In the case of property files only the properties that are marked 
  /// //Property/@Embed='false' are passed via the command line as it is assumed that the embedded 
  /// properties within the MSI are already there.
  /// </summary>
  /// <remarks>
  /// <code><![CDATA[<Msi.InstallPatch MspPath="mspPath" LogFile="logFile" LogOptions="logOptions" UserInterfaceLevel="userInterfaceLevel" LoadUserProfile="loadUserProfile" PropertyFiles="propertyFiles" Properties="properties" Features="features" />]]></code>
  /// <para>where:</para>
  /// <para><i>mspPath (Required)</i></para>
  /// <para>
  /// The path to the MSI to install.
  /// </para>
  /// <para><i>logFile (Required)</i></para>
  /// <para>
  /// The path to the log file for the installation. The recommended file name is the name of the MSI
  /// with the extension *.install.log.
  /// </para>
  /// <para><i>logOptions</i></para>
  /// <para>
  /// A delimited list of logging options. Possible values are: Default, StatusMessages, Warnings, Errors,
  /// ActionStart, ActionSpecificRequests, UserRequests, InitialParameters, OutOfMemory, TerminalProperties,
  /// Verbose, AppendLog, FlushEachLine, AllInformation. The default is Default. Please see the
  /// <see cref="Microsoft.Sdc.Tasks.Msi.MsiTaskBase.MsiLoggingOptions"/> documentation for
  /// further information.
  /// </para>
  /// <para><i>userInterfaceLevel</i></para>
  /// <para>
  /// The user interface level displayed by MsiExec during the installation. Possible values are: 
  /// None, Basic, ReducedWithModalDialog, FullWithModalDialog, NoneWithModalDialog, BasicWithModalDialog,
  /// BasicWithNoModalDialogs. The default is None. Please see the 
  /// <see cref="Microsoft.Sdc.Tasks.Msi.MsiTaskBase.MsiExecUILevel"/> documentation for
  /// further information.
  /// </para>
  /// <para><i>loadUserProfile</i></para>
  /// <para>
  /// <b>true</b> if the user's profile is loaded during the processing of the MSI, or <b>false</b> otherwise.
  /// This may be needed for some custom installation actions such as configuring ports and channels in 
  /// Microsoft BizTalk Server. The default is <b>false</b>.
  /// </para>
  /// <para><i>propertyFiles</i></para>
  /// <para>
  /// A delimited list of XML property files that provide installation properties for the MSI. 
  /// Multiple property files are allowed so that you can have a hierarchy - the first file provides a base set of properties
  /// (e.g. environmental properties for a particular rig) and subsequent files can override these to provide a more
  /// specific property or add new properties (e.g. properties for a machine, then properties for an individual MSI).
  /// </para>
  /// <para><i>properties</i></para>
  /// <para>
  /// A delimited list of installation properties in the format Name=Value. If any property files have been 
  /// specified, then the properties specified here are seen as the most significant and can overwrite 
  /// any of the property values specified in the files.
  /// </para>
  /// <para><i>features</i></para>
  /// <para>
  /// A delimited list of the names of features to be installed. This is not necessary if the MSI does not
  /// have features configured, or you wish all features to be installed.
  /// </para>
  /// </remarks>
  /// <example>
  /// <code><![CDATA[
  /// <Project>
  ///     <Target Name="Test">
  ///         <Msi.InstallPatch 
  ///             MspPath="C:\Build\Msi\Packages\MyPatch.msp" 
  ///             LogFile="C:\Build\Msi\Packages\MyPackage.install.log" 
  ///             LogOptions="Default;Verbose" 
  ///             UserInterfaceLevel="None" 
  ///             LoadUserProfile="true" 
  ///             PropertyFiles="C:\Build\Properties\Global.xml;C:\Build\Properties\Rig4.xml" 
  ///             Properties="INSTALLDIR=C:\Install;DOMAIN=rig4;MACHINE=r4app01"
  ///             Features="MSMQ,BTS2004,WebServices" />
  ///     </Target>
  /// </Project>
  /// ]]></code>  
  /// A sample property file is shown below. Note that you must include the namespace for the file to
  /// be parsed correctly.
  /// <code><![CDATA[
  /// <Properties xmlns="urn:sdc-microsoft-com:deployment:properties:v2.0">
  ///     <Property Name="MY_PROPERTY" Value="some value" />
  ///     <Property Name="ANOTHER_PROPERTY" Value="some other value" />
  ///     <Property Name="SOMETHING_ELSE" Value="hello world" />
  ///     ... etc ...
  /// </Properties>
  /// ]]></code>
  /// </example>
  #endregion
  public sealed class InstallPatch : MsiInstallTaskBase
  {
    /// <summary>
    /// Gets or sets the full or relative path to the MSI.
    /// </summary>
    /// <value>
    /// The full or relative path to the MSI.
    /// </value>
    [Required]
    public string MspPath
    {
      get
      {
        return (this.MsiPath == null) ? string.Empty : this.MsiPath;
      }

      set
      {
        this.MsiPath = value;
      }
    }

    /// <summary>
    /// hides the base implementation
    /// </summary>
    new private string MsiPath
    {
      get { return base.MsiPath; }
      set { base.MsiPath = value; }
    }

    /// <summary>
    /// hides the base implementation
    /// </summary>
    new private System.Guid ProductCode
    {
      get { return base.ProductCode; }
      set { base.ProductCode = value; }
    }

    /// <summary>
    /// Executes the task to install the MSI.
    /// </summary>
    /// <summary>
    /// Performs the action of this task.
    /// </summary>
    protected override void InternalExecute()
    {
      string msiExecArguments = BuildInstallPatchArgumentsAndExtractProperties(this.Features);
      this.RunMsiExecProcess(msiExecArguments);
    }
  }
}
